package com.zhiche.lisa.bms.service.quote.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.zhiche.lisa.bms.dao.mapper.quote.QuoteDtlMapper;
import com.zhiche.lisa.bms.dao.model.contract.Contract;
import com.zhiche.lisa.bms.dao.model.contract.ContractFleetDtl;
import com.zhiche.lisa.bms.dao.model.fee.FeePayable;
import com.zhiche.lisa.bms.dao.model.quote.QuoteDtl;
import com.zhiche.lisa.bms.pojo.bo.quote.FleetQuotation;
import com.zhiche.lisa.bms.pojo.vo.quote.QuoteExpandVO;
import com.zhiche.lisa.bms.service.contract.ContractFleetDtlService;
import com.zhiche.lisa.bms.service.fee.FeePayableService;
import com.zhiche.lisa.bms.service.prepay.PrepayBillService;
import com.zhiche.lisa.bms.service.price.PricePurchaseService;
import com.zhiche.lisa.bms.service.quote.QuoteDtlService;
import com.zhiche.lisa.bms.service.quote.QuoteService;
import com.zhiche.lisa.bms.service.utils.common.AccountBindUtil;
import com.zhiche.lisa.core.supports.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 报价单明细 服务实现类
 * </p>
 *
 * @author liuanshun
 * @since 2018-10-22
 */
@Service
@Slf4j
public class QuoteDtlServiceImpl extends ServiceImpl<QuoteDtlMapper, QuoteDtl> implements QuoteDtlService {
    @Autowired
    private QuoteService quoteService;
    @Autowired
    private FeePayableService feePayableService;
    @Autowired
    private PrepayBillService prepayBillService;
    @Autowired
    private PricePurchaseService pricePurchaseService;

    @Autowired
    private ContractFleetDtlService contractFleetDtlService;

    /**
     * 根据条件查询报价单详明
     *
     * @param condition
     * @return
     */
    @Override
    public List<QuoteDtl> selectQuoteDtlList(Map<String, Object> condition) {
        EntityWrapper<QuoteDtl> quoteDtlEntityWrapper = bindQuoteDtlWrapper(condition);
        List<QuoteDtl> quoteDtls = selectList(quoteDtlEntityWrapper);
        return quoteDtls;
    }

    @Override
    public List<QuoteDtl> selectQuoteDtlListNoTenant(Map<String, Object> condition) {
        List<QuoteDtl> quoteDtls = null;
        EntityWrapper<QuoteDtl> contractEntityWrapper = this.bindQuoteDtlWrapper(condition);
        quoteDtls = baseMapper.selectListNoTenant(contractEntityWrapper);
        return quoteDtls;
//		if (!CollectionUtils.isEmpty(quoteDtls = baseMapper.selectListNoTenant(contractEntityWrapper))) {
//			return quoteDtls;
//		}
//		else {
//			if (condition.containsKey("endProvince") && condition.containsKey("endCity") && condition.containsKey("endCounty") && condition.containsKey("endAddr")) {
//				HashMap<String, Object> removeEndAddrMap = new HashMap<>(condition);
//
//				if (!StringUtils.isEmpty(condition.get("endAddr"))) {
//					removeEndAddrMap.put("endAddr", "");
//					EntityWrapper<FleetQuotation> removeEndAddrEw = this.bindQuoteDtlWrapper(removeEndAddrMap);
//					if (!CollectionUtils.isEmpty(quoteDtls = baseMapper.selectListNoTenant(removeEndAddrEw))) {
//						return quoteDtls;
//					}
//				}
//				if (!StringUtils.isEmpty(condition.get("endCounty"))) {
//					removeEndAddrMap.put("endAddr", "");
//					EntityWrapper<FleetQuotation> removeEndAddrEw = this.bindQuoteDtlWrapper(removeEndAddrMap);
//					if (!CollectionUtils.isEmpty(quoteDtls = baseMapper.selectListNoTenant(removeEndAddrEw))) {
//						return quoteDtls;
//					}
//				}
//			}
//			if (condition.containsKey("startCity") && condition.containsKey("startCounty") && condition.containsKey("startAddr")) {
//				if (!StringUtils.isEmpty(condition.get("startAddr"))) {
//					condition.put("startAddr", "");
//					if (!CollectionUtils.isEmpty(quoteDtls = this.selectQuoteDtlListNoTenant(condition))) {
//						return quoteDtls;
//					}
//				}
//				if (!StringUtils.isEmpty(condition.get("startCounty"))) {
//					condition.put("startCounty", "");
//					if (!CollectionUtils.isEmpty(quoteDtls = this.selectQuoteDtlListNoTenant(condition))) {
//						return quoteDtls;
//					}
//				}
//			}
//			return quoteDtls;
//		}
    }

    /**
     * 根据headerId获取报价单详明
     *
     * @param id
     * @return
     */
    @Override
    public List<QuoteDtl> selectQuoteDtlsByHeaderId(Long id) {
        Map<String, Object> condition = new HashMap<String, Object>();
        condition.put("headId", id);
        return this.selectQuoteDtlList(condition);
    }

    @Override
    public List<QuoteDtl> selectQuoteDtlsByHeaderIds(List<Long> ids) {
        Map<String, Object> condition = new HashMap<String, Object>();
        condition.put("headIds", ids);
        return this.selectQuoteDtlList(condition);
    }

    /**
     * 根据报价单头单id修改应付账款的合同信息，并同时生成预付账单
     *
     * @param contract
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void updateFeePayableContactByHeaderId(Contract contract, Long headerId) {
        try {
            if (contract != null) {
                List<QuoteDtl> quoteDtls = this.selectQuoteDtlsByHeaderId(headerId);
                List<FeePayable> feePayables = new ArrayList<>();
                // 计算油卡费用
                List<ContractFleetDtl> contractFleetDtls = contractFleetDtlService.selectContractFleetDtlByContract(contract);
                List<Multimap> multimapList = Lists.newArrayList();
                for (QuoteDtl quoteDtl : quoteDtls) {
                    Long feeId = quoteDtl.getFeeId();
                    if (feeId != null) {
                        FeePayable feePayable = feePayableService.selectById(feeId);
                        feePayable.setContractCode(contract.getContCode());
                        // feePayable.setContractType(contract.getContractType() == 0 ? "临时" : "正式");
                        if (contract.getContractType() != null) {
                            feePayable.setContractType(String.valueOf(contract.getContractType()));
                        }
                        // feePayable.setKilometre(quoteDtl.getStandardMileage() == null ? BigDecimal.ZERO : quoteDtl.getStandardMileage());
                        // feePayable.setActualPrice(quoteDtl.getStandardPrice() == null ? BigDecimal.ZERO : quoteDtl.getStandardPrice());
                        // feePayable.setEstPrice(quoteDtl.getQuotationPrice() == null ? BigDecimal.ZERO : quoteDtl.getQuotationPrice());
                        feePayable.setKilometre(quoteDtl.getQuotationMileage() == null ? BigDecimal.ZERO : quoteDtl.getQuotationMileage());
                        feePayable.setActualPrice(quoteDtl.getQuotationPrice() == null ? BigDecimal.ZERO : quoteDtl.getQuotationPrice());
                        feePayable.setEstPrice(quoteDtl.getStandardPrice() == null ? BigDecimal.ZERO : quoteDtl.getStandardPrice());
                        feePayable.setActualAmt(feePayable.getActualPrice().multiply(feePayable.getKilometre()));
                        // 2019-01-12 暂估价
                        feePayable.setEstAmt(feePayable.getEstPrice().multiply(feePayable.getKilometre()));
                        // 报价单id
                        feePayable.setQuoteId(quoteDtl.getHeadId());
                        // 计算现金油卡比例
                        Multimap<String, BigDecimal> stringBigDecimalMultimap = feePayableService.computeOilRate(contractFleetDtls, feePayable, contract);
                        if (stringBigDecimalMultimap != null && !multimapList.contains(stringBigDecimalMultimap)) {
                            multimapList.add(stringBigDecimalMultimap);
                        }

                        // 2019-01-18 保险费
                        feePayable.setElsePrice(BigDecimal.ZERO);
                        feePayables.add(feePayable);
                        // prepayBillService.insertPrepayBill(feePayable, contract);
                        prepayBillService.createPrepayBillByContract(feePayable, contract);

                        //根据车架号修改支付价格
                        if (feePayable.getVin() != null) {
                            pricePurchaseService.updateExtPurchasePriceByItemUidNoTenant(feePayable);
                        }
                    }
                }
                if (!CollectionUtils.isEmpty(feePayables)) {
                    // 2019-01-18 保险费
                    feePayables.get(0).setElsePrice(contract.getCashDeposit());
                    feePayableService.updateBatchById(feePayables);
                }
                // 修改
                computeRateOilAndCash(multimapList);
            }
        } catch (BaseException e) {
            log.error("QuoteDtlServiceImpl.updateFeePayableContactByHeaderId error: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("QuoteDtlServiceImpl.updateFeePayableContactByHeaderId error: {}", e.getMessage());
            throw new BaseException("修改应付账款数据失败");
        }
    }

    /**
     * 计算均摊不完成的数据
     *
     * @param multimapList
     */
    private void computeRateOilAndCash(List<Multimap> multimapList) {
        if (!CollectionUtils.isEmpty(multimapList)) {
            List<FeePayable> updateList = Lists.newArrayList();
            multimapList.forEach(map -> {
                Set keySet = map.keySet();
                keySet.forEach(key -> {
                    List<BigDecimal> sumList = Lists.newArrayList(map.get(key));
                    BigDecimal oilSum = sumList.get(0);
                    BigDecimal cashSum = sumList.get(1);
                    FeePayable feePayable = feePayableService.selectCashAndOilSumNoTenant(key.toString());
                    // 0-油 1-现金
                    if (feePayable.getOilBaPay().subtract(oilSum).compareTo(BigDecimal.ZERO) != 0
                            || feePayable.getCashBaPay().subtract(cashSum).compareTo(BigDecimal.ZERO) != 0) {
                        FeePayable updateFeePayable = feePayableService.selectById(feePayable.getId());
                        updateFeePayable.setOilBaPay(updateFeePayable.getOilBaPay().add(oilSum.subtract(feePayable.getOilBaPay())));
                        updateFeePayable.setCashBaPay(updateFeePayable.getCashBaPay().add(cashSum.subtract(feePayable.getCashBaPay())));
                        updateList.add(updateFeePayable);
                    }
                });
            });
            if (!CollectionUtils.isEmpty(updateList)) {
                feePayableService.updateBatchById(updateList);
            }
        }
    }


    /**
     * 根据详细数据和头id进行新增
     *
     * @param quoteDtls
     * @param headerId
     * @return
     */
    @Override
    public List<QuoteDtl> insertQuotesBySourceAndHeaderId(List<QuoteDtl> quoteDtls, Long headerId) {
        try {
            if (CollectionUtils.isEmpty(quoteDtls)) {
                quoteDtls = null;
            } else {
                AccountBindUtil<QuoteDtl> quoteDtlAccountBindUtil = new AccountBindUtil<>();
                quoteDtls.forEach(quoteDtl -> {
                    quoteDtl.setHeadId(headerId);
                    quoteDtl.setGmtCreate(new Date());
                    quoteDtlAccountBindUtil.bindCreatorAndTenantId(quoteDtl, false);
                });
                insertBatch(quoteDtls);
            }
        } catch (BaseException e) {
            log.error("QuoteDtlServiceImpl.insertQuotesBySourceAndHeaderId error: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("QuoteDtlServiceImpl.insertQuotesBySourceAndHeaderId error: {}", e.getMessage());
            throw new BaseException("新增报价单详明出现错误");
        }
        return quoteDtls;
    }

    /**
     * 批量更新报价信息
     *
     * @param quoteDtls
     * @return
     */
    @Override
    public List<QuoteDtl> updateQuotes(List<QuoteDtl> quoteDtls) {
        try {
            if (CollectionUtils.isEmpty(quoteDtls)) {
                quoteDtls = null;
            } else {
                quoteDtls.forEach(quoteDtl -> {
                    quoteDtl.setGmtModify(new Date());
                });
                updateBatchById(quoteDtls);
            }
        } catch (BaseException e) {
            log.error("QuoteDtlServiceImpl.updateQuotes error: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("QuoteDtlServiceImpl.updateQuotes error: {}", e.getMessage());
            throw new BaseException("修改报价单详明出现错误");
        }
        return quoteDtls;
    }

    /**
     * 根据详细数据和头id进行编辑
     *
     * @param quoteDtls
     * @param headerId
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public List<QuoteDtl> editQuotesBySourceAndHeaderId(List<QuoteDtl> quoteDtls, Long headerId) {
        try {
            if (CollectionUtils.isEmpty(quoteDtls)) {
                quoteDtls = null;
            } else {
                /*
                 * 获取原有的id号
                 */
                EntityWrapper<QuoteDtl> allIdEw = new EntityWrapper<>();
                allIdEw.eq("head_id", headerId);
                allIdEw.setSqlSelect("id");
                List<Object> idObjs = selectObjs(allIdEw);
                List<Long> ids = new ArrayList<>();
                if (!CollectionUtils.isEmpty(idObjs)) {
                    idObjs.forEach(o -> ids.add((Long) o));
                }
                /*
                 * 遍历数组，对比新旧id组判断新增编辑和删除的数据
                 */
                List<QuoteDtl> addQuoteDtls = new ArrayList<>();
                List<QuoteDtl> updateQuoteDtls = new ArrayList<>();

                quoteDtls.forEach(quoteDtl -> {
                    //该次只保存修改后还存在的数据（新增的和编辑的）
                    if (ids.contains(quoteDtl.getId())) {
                        ids.remove(quoteDtl.getId());
                        //编辑
                        updateQuoteDtls.add(quoteDtl);
                    } else {
                        //新增
                        addQuoteDtls.add(quoteDtl);
                    }
                });
                /*
                 * 执行数组库保存操作
                 */
                this.insertQuotesBySourceAndHeaderId(addQuoteDtls, headerId);
                this.updateQuotes(updateQuoteDtls);
                if (!CollectionUtils.isEmpty(ids)) {
                    deleteBatchIds(ids);
                }
            }
        } catch (BaseException e) {
            log.error("QuoteDtlServiceImpl.editQuotesBySourceAndHeaderId error: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("QuoteDtlServiceImpl.editQuotesBySourceAndHeaderId error: {}", e.getMessage());
            throw new BaseException("编辑报价单详明出现错误");
        }
        return quoteDtls;
    }

    /**
     * 根据条件报价单规则明细
     *
     * @param condition
     * @return
     */
    @Override
    public List<FleetQuotation> selectFleetQuotation(Map<String, Object> condition) {
        Wrapper<FleetQuotation> qw = buildQuotaCondition(condition);
        return baseMapper.selectFleetQuotation(qw);
    }

    private Wrapper<FleetQuotation> buildQuotaCondition(Map<String, Object> condition) {
        EntityWrapper<FleetQuotation> qw = new EntityWrapper();
        if (Objects.isNull(condition)) {
            return qw;
        }

        for (Map.Entry<String, Object> entry : condition.entrySet()) {
            if (entry.getKey().equals("subid") && isNotBlank(entry.getValue())) {
                qw.eq("sub_id", entry.getValue());
            }
            if (entry.getKey().equals("headIds") && isNotBlank(entry.getValue())) {
                qw.in("head_id", JSONArray.parseArray(JSONObject.toJSONString(entry.getValue())));
            }
        }
        return qw;
    }

    private boolean isNotBlank(Object value) {
        return Objects.nonNull(value) && org.apache.commons.lang3.StringUtils.isNotBlank(value.toString());
    }

    /**
     * 获取明细数据
     *
     * @param quoteId
     * @return
     */
    @Override
    public List<QuoteExpandVO> getQuoteExpandByQuoteId(Long quoteId) {
        if (Objects.nonNull(quoteId)) {
            return baseMapper.getQuoteExpandByQuoteId(quoteId);
        }
        return null;
    }

    /**
     * 批量获取明细数据
     *
     * @param quoteIdList
     * @return
     */
    @Override
    public List<QuoteExpandVO> getQuoteExpandByQuoteIdList(List<Long> quoteIdList) {
        if (!CollectionUtils.isEmpty(quoteIdList)) {
            return baseMapper.getQuoteExpandByQuoteIdList(quoteIdList);
        }
        return null;
    }

    /**
     * 绑定详明查询条件
     *
     * @param condition
     * @return
     */
    private EntityWrapper<QuoteDtl> bindQuoteDtlWrapper(Map<String, Object> condition) {
        EntityWrapper<QuoteDtl> entityWrapper = new EntityWrapper<QuoteDtl>();

        if (!CollectionUtils.isEmpty(condition)) {
            List<String> areNullList = new ArrayList<>();

            entityWrapper.orderBy("gmt_create desc, id desc");
            for (Map.Entry<String, Object> item :
                    condition.entrySet()) {
                if (!StringUtils.isEmpty(item.getValue())) {
                    if ("headId".equals(item.getKey())) {
                        entityWrapper.eq("head_id", item.getValue());
                    }
                    if ("headIds".equals(item.getKey())) {
                        entityWrapper.in("head_id", JSONArray.parseArray(item.getValue().toString()));
                    }
                    if ("id".equals(item.getKey())) {
                        entityWrapper.eq("id", item.getValue());
                    }
                    if ("ids".equals(item.getKey())) {
                        entityWrapper.in("id", JSONArray.parseArray(item.getValue().toString()));
                    }
                    if ("vehicleTypeName".equals(item.getKey())) {
                        entityWrapper.eq("vehicle_type_name", item.getValue());
                    }
                    if ("transTypeName".equals(item.getKey())) {
                        entityWrapper.eq("trans_type_name", item.getValue());
                    }
                    if ("client".equals(item.getKey())) {
                        entityWrapper.eq("client", item.getValue());
                    }
                    if ("staPriceId".equals(item.getKey())) {
                        entityWrapper.eq("sta_price_id", item.getValue());
                    }
                }
            }


            if (condition.containsKey("startCity")) {
                Object endCounty = condition.get("startCity");
                if (StringUtils.isEmpty(endCounty)) {
                    areNullList.add("start_city");
                } else {
                    entityWrapper.eq("start_city", endCounty);
                }
            }
            if (condition.containsKey("startCounty")) {
                Object endCounty = condition.get("startCounty");
                if (StringUtils.isEmpty(endCounty)) {
                    areNullList.add("start_county");
                } else {
                    entityWrapper.eq("start_county", endCounty);
                }
            }
            if (condition.containsKey("startAddr")) {
                Object endCounty = condition.get("startAddr");
                if (StringUtils.isEmpty(endCounty)) {
                    areNullList.add("start_addr");
                } else {
                    entityWrapper.eq("start_addr", endCounty);
                }
            }
            if (condition.containsKey("endProvince")) {
                Object endCounty = condition.get("endProvince");
                if (StringUtils.isEmpty(endCounty)) {
                    areNullList.add("end_province");
                } else {
                    entityWrapper.eq("end_province", endCounty);
                }
            }
            if (condition.containsKey("endCity")) {
                Object endCounty = condition.get("endCity");
                if (StringUtils.isEmpty(endCounty)) {
                    areNullList.add("end_city");
                } else {
                    entityWrapper.eq("end_city", endCounty);
                }
            }
            if (condition.containsKey("endCounty")) {
                Object endCounty = condition.get("endCounty");
                if (StringUtils.isEmpty(endCounty)) {
                    areNullList.add("end_county");
                } else {
                    entityWrapper.eq("end_county", endCounty);
                }
            }
            if (condition.containsKey("endAddr")) {
                Object endCounty = condition.get("endAddr");
                if (StringUtils.isEmpty(endCounty)) {
                    areNullList.add("end_addr");
                } else {
                    entityWrapper.eq("end_addr", endCounty);
                }
            }

            Object isNullItem = condition.get("isNull");
            if (!StringUtils.isEmpty(isNullItem)) {
                String[] split = (String[]) isNullItem;
                if (!ArrayUtils.isEmpty(split)) {
                    areNullList.addAll(Arrays.asList(split));
                }
            }
            if (!CollectionUtils.isEmpty(areNullList)) {
                for (String item :
                        areNullList) {
                    if (!StringUtils.isEmpty(item)) {
                        entityWrapper.andNew().isNull(item).or().eq(item, "");
                    }
                }
            }
        }
        return entityWrapper;
    }
}
